package cn.com.vs.service;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;

import cn.com.vs.Configurator;
import cn.com.vs.DBManager;
import cn.com.vs.api.UserApi;
import cn.com.vs.model.ApplicationInfo;
import cn.com.vs.model.ContactItem;
import cn.com.vs.service.domain.Comment;
import cn.com.vs.service.domain.Group;
import cn.com.vs.service.domain.Member;
import cn.com.vs.service.domain.Talk;
import cn.com.vs.service.domain.UserData;
import cn.com.vs.service.domain.UserInfo;
import cn.com.vs.service.mapper.BasicSqlMapper;
import cn.com.vs.utils.DBUtils;
import cn.com.vs.utils.NoticeUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.hash.Hashing;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.mashape.unirest.request.GetRequest;
import com.mashape.unirest.request.HttpRequestWithBody;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;
import com.qiniu.http.Response;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;

public class UserService {
	private static UserService service = new UserService();

	public static UserService getInstance(){
		return service;
	}

	public enum RetCode{
		OK("成功",0),
		SQL_ERROR("SQL执行异常",100),
		ORIGIN_PWD_ERROR("原始密码不正确",101),
		CONTACT_EXIST("该联系人已存在",102),
		CONTACT_WAITFORAUTH("联系人已经添加，等待对方验证",103),
		CONTACT_ADDOK("联系人已经添加成功",104),
		IM_ADDFRIENDERROR("添加IM联系人失败",105),
		CONTACT_NOT_EXIST("该联系人不存在",106),
		CONTACT_CANNOTADDSELF("不能添加自己",107),
		CRATE_IMGROUP_FAILD("创建聊天组失败",108),
		CONTACT_NOT_MEMBER("未加入群组不能查看群组成员",109),
		CONTACT_ADD_REJECT("添加操作被对方拒绝",110),
		MAX_LIMITED("达到最大数量限制",111),
		NOT_OWNER("非拥有者,没有权限执行该操作",112),
		IM_DELETEGROUPFAILD("删除IM群失败",113),
		TARGET_NOT_EXIST("目标对象不存在",123),
		LOCATION_CREATE_FAILD("创建地图数据失败",124),
		LOCATION_UPDATE_FAILD("更新地图数据失败",125),
		TALK_PUBLISH_FAILD("发布信息失败",150),
		COMMENT_PUBLISH_FAILD("评论信息提交失败",151),
		TALK_DELETE_FAILD("删除信息失败",152),
		TALK_TYPE_INVALID("无效的类型",153),
		TALK_INDEX_OUTOFRANGE("指定索引超出范围",154);
		private String desc;
		private int    code;

		RetCode(String desc,int code){
			this.desc = desc;
			this.code = code;
		}
		public String getDesc(){
			return desc;
		}
		public int getCode(){
			return code;
		}
	}

	public JSONObject userLogin(String value,String pwd,String type)
	{
		Object thirdLoginRes = null;
		if( type.compareToIgnoreCase("wechatapp") == 0 ){
			thirdLoginRes = getWechatInfo(value, true);
		}else if( type.compareToIgnoreCase("wechatweb") == 0 ){
			thirdLoginRes = getWechatInfo(value, false);
		}
		String ak = Configurator.getInstance().getString("qiniu_accesstoken");
		String sk =  Configurator.getInstance().getString("qiniu_secretkey");
		String uploadToken = "";
		if( StringUtils.isNotEmpty(ak) && StringUtils.isNotEmpty(sk)){
			Auth auth = Auth.create(ak, sk);
			String bucket = Configurator.getInstance().getString("qiniu_bucket");
			uploadToken = auth.uploadToken(bucket);
		}
		if( thirdLoginRes != null ){
			if( thirdLoginRes instanceof String ){
				JSONObject res = new JSONObject();
				res.put("ok", false);
				res.put("message", (String)thirdLoginRes);
				return res;
			}else{
				// 查看是否已经绑定过，若没有则新注册并绑定登录
				JSONObject wechatInfo = (JSONObject)thirdLoginRes;
				String openid = wechatInfo.getString("openid");
				if( !UserService.getInstance().accountExist(openid,type) ){
					// 新自动注册并登录
					JSONObject info = new JSONObject();
					boolean ret = createAccount(openid, "",
							type,"","-1",info);
					if( !ret )
					{
						info.put("ok", false);
						info.put("message", "为微信登录创建账号时失败");
						return info;
					}
					// 创建账号成功，继续后续流程
					// 将微信nick等数据设置给新创建的账号
					SqlSession session = null;
					try{
						session = DBUtils.getSqlSession(false);
						BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
						Map<String,Object> map = new HashMap<String,Object>();
						String uuid = UUID.randomUUID().toString();
						String account = info.getString("account");
						if( wechatInfo.containsKey("username"))
							map.put("username", wechatInfo.getString("username"));
						if( wechatInfo.containsKey("nickname"))
							map.put("nickname", wechatInfo.getString("nickname"));
						if( wechatInfo.containsKey("sex"))
							map.put("sex", wechatInfo.getInteger("sex"));
						if( wechatInfo.containsKey("location"))
							map.put("location", wechatInfo.getString("city"));
						if( wechatInfo.containsKey("headimgurl")){
							String header = wechatInfo.getString("headimgurl");
							String key = account+"/avatar/"+uuid;
							map.put("avatarImg",key);
							GetRequest req = Unirest.get(header);
							HttpResponse<InputStream> resp = req.asBinary();
							if( resp.getStatus() == 200 ){
								InputStream is = resp.getBody();
								ByteArrayOutputStream out = new ByteArrayOutputStream();
								byte[] temp = new byte[1024];
								for(int len = is.read(temp); len != -1;len = is.read(temp)){
									out.write(temp, 0, len);
								}
								UploadManager uploadManager = new UploadManager();
								Response res = uploadManager.put(out.toByteArray(), key, uploadToken);
								if( !res.isOK() ){
									System.out.println("图片["+key+"]转存上传失败...");
								}
							}
						}
						
						mapper.setUserInfo(map);
						
						
					}catch(Exception e){
						e.printStackTrace();
					}
				}else{
					// 账号已经存在，直接后续流程
				}
			}

		}
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> params = new HashMap<String,Object>();
			params.put("value", value);
			params.put("passwd", pwd);
			params.put("type", type);
			UserInfo info = mapper.userLogin(params);
			if( info == null ){
				int exist = mapper.userExistTest(params);
				JSONObject result = new JSONObject();
				if( exist > 0 ){
					result.put("message","密码验证错误");
					result.put("ok",false);
				}else{
					result.put("message","账户不存在");
					result.put("ok",false);
				}
				return result;
			}
			if( StringUtils.isBlank(info.getNickName()) ){
				info.setNickName( info.getAccount() );
			}
			JSONObject result = (JSONObject)JSON.toJSON( info );
			if( info != null ){
				String imToken = Hashing.md5().hashBytes(info.getAccount().getBytes()).toString();
				result.put("imToken", imToken);
			}
			result.put("uploadToken", uploadToken);
			return result;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}


	private Object getWechatInfo(String wcode,boolean isApp){
		String appKey = isApp?"wechat_appkey":"wechat_webkey";
		String skKey = isApp?"wechat_secretkey":"wechat_websecretkey";
		String appid = Configurator.getInstance().getString(appKey);
		String appsecret =  Configurator.getInstance().getString(skKey);

		HttpRequestWithBody req = Unirest.post("https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appid+"&"+
				"secret="+appsecret+"&code="+
				wcode+"&grant_type=authorization_code");
		try {
			HttpResponse<String> result = req.asString();
			if( result.getStatus() == 200 ){
				String body = result.getBody();
				JSONObject dat = JSON.parseObject(body);
				String errMsg = dat.getString("errmsg");
				if( !StringUtils.isEmpty(errMsg) ){
					return "获取微信用户信息失败:"+errMsg+" 错误码:"+dat.getInteger("errcode");
				}
				String accessToken = dat.getString("access_token");
				String openid = dat.getString("openid");
				String userinfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+accessToken+"&openid="+openid+"&lang=zh_CN";
				req = Unirest.post( userinfoUrl );
				result = req.asString();
				if( result.getStatus() == 200 ){
					body = result.getBody();
					dat = JSON.parseObject(body);
					//logger.debug(dat);
					errMsg = dat.getString("errmsg");
					if( !StringUtils.isEmpty(errMsg) ){
						return "获取微信用户信息失败:"+errMsg+" 错误码:"+dat.getInteger("errcode");
					}
					dat.put("openid", openid);
					return dat;
				}else{
					return "获取微信用户信息时响应码错误:"+result.getStatus();
				}
			}else{
				return "微信验证权限时响应码错误:"+result.getStatus();
			}
		} catch (UnirestException e) {
			e.printStackTrace();
			return "微信验证权限时异常:"+e.getLocalizedMessage();
		}
	}

	public JSONObject checkUser(String bindtype, String bindvalue) {
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			List<Map<String,?>> list = mapper.getUseId(bindtype, bindvalue);

			if(list != null && list.size() > 0) {
				JSONObject result = new JSONObject();
				result.put("userId", (Integer)((Map<String,?>)list.get(0)).get("userId"));
				result.put("name", (String)((Map<String,?>)list.get(0)).get("name"));
				result.put("account", (String)((Map<String,?>)list.get(0)).get("account"));
				return result;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}

		return null; 
	}

	public JSONArray getWechatAppMembers(String appid)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> params = new HashMap<String,Object>();
			params.put("wechatAppID", appid);
			List<Map<String,?>> result = mapper.getWechatAccountInfo(params);
			JSONArray array = new JSONArray();
			for( Map<String,?> row:result ){
				JSONObject res = new JSONObject();
				res.put( "openid", row.get("bindvalue"));
				res.put( "userid", row.get("userid"));
				res.put( "account", row.get("account"));
				res.put( "nickname", row.get("name"));
				res.put( "location", row.get("location") );
				array.add( res );
			}
			return array;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}

	public boolean createAccount(String value,String userPWD,
			String accoutType,String accessToken,String expireTime,JSONObject info){
		Connection conn = null;
		try{
			conn = DBManager.getInstance().getConnection();
			conn.setAutoCommit(false);
			{
				CallableStatement cst = conn.prepareCall("call proc_createAccount(?,?,?,?,?,?,?,?)");
				try{
					cst.setString(1, value);
					cst.setString(2, userPWD);
					cst.setString(3, accoutType);
					cst.setString(4, accessToken);
					cst.setInt(5, Integer.parseInt(expireTime));
					cst.registerOutParameter(6, java.sql.Types.VARCHAR); 
					cst.registerOutParameter(7, java.sql.Types.INTEGER);
					cst.registerOutParameter(8, java.sql.Types.INTEGER); 
					int ret = cst.executeUpdate();
					if( ret == 0 ){
						Integer transactionStatus = cst.getInt(8);
						if( transactionStatus == 1 ){
							return false;
						}
						// 将账号信息在远程注册
						String accountName = cst.getString(6);
						Integer id = cst.getInt(7);
						info.put("account", accountName );
						info.put("id", id );
						String imtoken = Hashing.md5().hashBytes(accountName.getBytes()).toString();
						if( IMService.getInstance().createIMAccount(accountName, 
								imtoken,
								accountName)){
							conn.commit();
							info.put("imToken",imtoken);
							//如果是电话注册则获取相关的联系人，发送通知
							if( "PHONE".compareToIgnoreCase(accoutType)==0 ){
								SqlSession session = null;
								try{
									session = DBUtils.getSqlSession();
									BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
									List<Map<String,?>> result = mapper.getContactsWithPhone( value );
									List<String> infos = new ArrayList<String>();
									for( Map<String,?> mp : result ){
										Integer uid = (Integer)mp.get("userid");
										JSONObject json = new JSONObject();
										String cid = (String)mp.get("cid");
										json.put("cid", cid);
										json.put("account", accountName);
										json.put("userid", id);
										infos.add(json.toJSONString());
										NoticeUtils.makeNewContactRegistedNotice(uid, json.toJSONString());
									}
								}catch(Exception e){
									e.printStackTrace();
								}finally{
									if( session != null )
										session.close();
								}
							}
							return true;
						}else{
							conn.rollback();
							return false;
						}
					}
					return false;
				}catch(Exception e){
					e.printStackTrace();
					conn.rollback();
				}finally{
					if(cst!=null)
						cst.close();
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( conn != null ){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}

	public boolean deleteAccount(int userid)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			String acc = mapper.getUserAccount(userid);
			int nDel = mapper.deleteAccount( userid );
			if( nDel > 0 ){
				IMService.getInstance().deleteIMAccount(acc);
				return true;
			}
			return false;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return false;
	}


	public JSONObject getUserInfo( Integer userid )
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			UserInfo ui = mapper.getUserInfo(userid);
			if( ui != null ){
				JSONObject result = (JSONObject)JSON.toJSON( ui );
				if( ui != null ){
					String imToken = Hashing.md5().hashBytes(ui.getAccount().getBytes()).toString();
					result.put("imToken", imToken);
				}
				return result;
			}
			return null;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;	
	}

	static String checkThirdAccountSql = "select count(*) from nk_user a,nk_user_bind nkb where a.id = nkb.account_id and nkb.bindvalue = ? and nkb.bindtype = ?";
	static String checkAccountSql = "select count(*) from nk_user where account = ?";
	public boolean accountExist(String account,String type){
		Connection conn = null;
		try{
			conn = DBManager.getInstance().getConnection();
			PreparedStatement st = null;
			if( type.compareToIgnoreCase("NK") == 0 ){
				st = conn.prepareStatement(checkAccountSql);
				st.setString( 1, account );
			}else{
				st = conn.prepareStatement(checkThirdAccountSql);
				st.setString(1, account);
				st.setString(2, type);
			}

			ResultSet rs = st.executeQuery();
			if( rs.next() && rs.getInt(1) != 0  ){
				rs.close();
				st.close();
				return true;
			}
			rs.close();
			st.close();
			return false;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( conn != null ){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}

	public RetCode bindUserData(UserData data){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			int ret = mapper.bindUserData(data);
			if( ret > 0 ){
				return RetCode.OK;
			}else{
				return RetCode.SQL_ERROR;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public boolean updateNickName(String account,String nickName){
		Connection conn = null;
		try{
			conn = DBManager.getInstance().getConnection();
			conn.setAutoCommit(false);
			PreparedStatement st = conn.prepareStatement("update nk_user set name=? where account=?");
			try{
				st.setString(1, nickName );
				st.setString(2, account );
				int ret = st.executeUpdate();
				if( ret == 1 ){
					if( IMService.getInstance().updateNickName(account, nickName) ){
						conn.commit();
						st.close();
						return true;
					}
					else{
						conn.rollback();
						st.close();
						return false;
					}
				}
				return false;
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				if(st!=null)
					st.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( conn != null ){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}

	/**
	 * 更新用户密码
	 * @param account
	 * @param oldpwd
	 * @param passwd
	 * @return
	 */
	public RetCode updatePasswd(String account,String oldpwd,String passwd){
		Connection conn = null;
		try{
			conn = DBManager.getInstance().getConnection();
			PreparedStatement st = conn.prepareStatement("update nk_user set pass=? where account=? and pass=?");
			try{
				st.setString(1, passwd );
				st.setString(2, account );
				st.setString(3, oldpwd );
				int ret = st.executeUpdate();
				if( ret == 1 ){
					st.close();
					return RetCode.OK;
				}
				return RetCode.ORIGIN_PWD_ERROR;
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				if(st!=null)
					st.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( conn != null ){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return RetCode.SQL_ERROR;
	}

	public RetCode resetPassword(String newpwd,int userid)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> params = new HashMap<String,Object>();
			params.put("userid", userid);
			params.put("password", newpwd);
			int ret = mapper.resetPWD(params);
			return ret>0?RetCode.OK:RetCode.TARGET_NOT_EXIST;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public RetCode updateUserInfo( Map<String,Object> map ){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession(false);
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			int ret = mapper.setUserInfo(map);
			/*
			if( ret > 0 ){
				String nickname = (String)map.get("nickname");
				if( nickname != null ){
					IMService.getInstance().updateNickName((String)map.get("account"), nickname);
				}
			}
			 */
			return ret>0?RetCode.OK:RetCode.TARGET_NOT_EXIST;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public RetCode updateUserPosition(JSONObject accountInfo,String latitude,String longitude){
		SqlSession session = null;
		try{
			Integer userid = accountInfo.getInteger("id");
			String name = accountInfo.getString("name");
			if( StringUtils.isBlank(name) )
				name = accountInfo.getString("account");
			Integer type = accountInfo.getIntValue("type");
			Integer locid = accountInfo.getInteger("locationid");
			locid = (locid==null||locid==0)?null:locid;
			if( locid == null ){
				locid = CloudMapService.getInstance().createUserLocData(name, longitude, latitude, type, userid);
				if( locid > 0 ){
					session = DBUtils.getSqlSession();
					BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
					Map<String,Object> params = new HashMap<String,Object>();
					params.put("id", userid);
					params.put("userType", type);
					params.put("locationid", locid);
					mapper.setUserLoacationID(params);
					accountInfo.put("locationid", locid);
					RedisService.getInstance().setValue(accountInfo.getString("token"), accountInfo.toJSONString(),UserApi.token_alive );
				}else{
					return RetCode.LOCATION_CREATE_FAILD;
				}
			}else{
				if( !CloudMapService.getInstance().updateUserLocData(locid, name, longitude, latitude) )
					return RetCode.LOCATION_UPDATE_FAILD;
			}
			return RetCode.OK;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public boolean updateAvator(String account,String img,String thumb){
		Connection conn = null;
		try{
			conn = DBManager.getInstance().getConnection();
			PreparedStatement st = conn.prepareStatement("update nk_user set avatarImg=?,thumbImg=? where account=?");
			try{
				st.setString(1, StringUtils.isBlank(img)?"":img);
				st.setString(2, StringUtils.isBlank(thumb)?"":thumb);
				st.setString(3, account );
				int ret = st.executeUpdate();
				if( ret == 1 ){
					st.close();
					return true;
				}
				return false;
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				if(st!=null)
					st.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( conn != null ){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}


	public int getUserCount(String account){
		Connection conn = null;
		try{
			conn = DBManager.getInstance().getConnection();
			String sql = "select count(*) from nk_user where account<>? and status=1 ";
			PreparedStatement st = conn.prepareStatement(sql);
			try{
				st.setString(1, account );
				ResultSet rs = st.executeQuery();
				int count = 0;
				while(rs.next()){
					count = rs.getInt(1);
				}
				rs.close();
				return count;
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				if(st!=null)
					st.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( conn != null ){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return 0;
	}

	public List<ContactItem> getUserList(String account,Integer from,Integer limit){
		Connection conn = null;
		try{
			conn = DBManager.getInstance().getConnection();
			String sql = "select * from nk_user where account<>? and status=1 ";

			if( from != null ){
				if( limit == null )
					sql += "limit ?";
				else
					sql += "limit ?,?";
			}
			PreparedStatement st = conn.prepareStatement(sql);
			try{
				st.setString(1, account );
				if( from != null )
					st.setInt(2, from );
				if( limit !=null)
					st.setInt(3, limit );
				ResultSet rs = st.executeQuery();
				List<ContactItem> res = new ArrayList<ContactItem>();
				while(rs.next()){
					ContactItem ci = new ContactItem();
					String name = rs.getString("name");
					int id = rs.getInt("id");
					String avatar = rs.getString("avatarImg");
					String thumb = rs.getString("thumbImg");
					int role = rs.getInt("role");
					ci.setAccount( rs.getString("account"));
					ci.setId( id );
					int locid = rs.getInt("locationid");
					ci.setLocationid(locid);
					ci.setName( name );
					ci.setAvatar( StringUtils.isEmpty(avatar)?"":avatar );
					ci.setAvatarThumb( StringUtils.isEmpty(thumb)?"":thumb );
					if( role == 1 )
						ci.setType( 3 ); //admin
					res.add( ci );
				}
				rs.close();
				return res;
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				if(st!=null)
					st.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( conn != null ){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}

		return Collections.emptyList();
	}

	public boolean updateUserRole(String userid,int roleID){
		Connection conn = null;
		try{
			conn = DBManager.getInstance().getConnection();
			PreparedStatement st = conn.prepareStatement("update nk_user set role=? where id=?");
			try{
				st.setInt(1, roleID );
				st.setInt(2, Integer.parseInt(userid) );
				int ret = st.executeUpdate();
				if( ret == 1 ){
					st.close();
					return true;
				}
				return false;
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				if(st!=null)
					st.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( conn != null ){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}

	public List<ContactItem> getContacts(Integer id,Integer type,Integer from,Integer limit)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Integer> params = new HashMap<String,Integer>();
			params.put("id", id);
			params.put("type", type);
			params.put("from", from);
			params.put("limit", limit);
			List<Map<String,?>> result = mapper.selectAllContact( params );
			List<ContactItem> list = new ArrayList<ContactItem>();
			for( Map<String,?> r : result ){
				ContactItem item = new ContactItem();
				item.setId( (Integer)r.get("id") );
				String name = (String)r.get("name");
				item.setName( StringUtils.isBlank(name)?(String)r.get("account"):name );
				String avatar = (String)r.get("avatarImg");
				item.setAvatar( avatar==null?"":avatar );
				String thumb = (String)r.get("thumbImg");
				item.setAvatarThumb( thumb==null?"":thumb );
				item.setType( (Integer)r.get("type") );
				item.setAccount( (String)r.get("account") );
				item.setLocationid( r.get("locationid") == null?0:(Integer)r.get("locationid"));
				Object gender = r.get("sexuality");
				if( gender == null ){
					item.setSexuality( (Integer)0 );
				}else if( gender instanceof Long ){
					item.setSexuality( ((Long)gender).intValue() );
				}else if(gender instanceof Integer ){
					item.setSexuality( (Integer)gender );
				}
				item.setFlag((Integer)r.get("flag"));
				item.setCv((Integer)r.get("cv"));
				item.setVid((String)r.get("vid"));
				item.setOwner((Integer)r.get("owner"));
				list.add( item );
			}
			return list;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			if( session != null )
				session.close();
		}
	}

	public List<ContactItem> syncContacts(Integer id,Integer type, Integer cv, Integer from,Integer limit)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Integer> params = new HashMap<String,Integer>();
			params.put("id", id);
			params.put("type", type);
			params.put("cv", cv);
			params.put("from", from);
			params.put("limit", limit);
			List<Map<String,?>> result = mapper.syncAllContact( params );
			List<ContactItem> list = new ArrayList<ContactItem>();
			for( Map<String,?> r : result ){
				ContactItem item = new ContactItem();
				item.setId( (Integer)r.get("id") );
				String name = (String)r.get("name");
				item.setName( StringUtils.isBlank(name)?(String)r.get("account"):name );
				String avatar = (String)r.get("avatarImg");
				item.setAvatar( avatar==null?"":avatar );
				String thumb = (String)r.get("thumbImg");
				item.setAvatarThumb( thumb==null?"":thumb );
				item.setType( (Integer)r.get("type") );
				item.setAccount( (String)r.get("account") );
				item.setLocationid( r.get("locationid") == null?0:(Integer)r.get("locationid"));
				Object gender = r.get("sexuality");
				if( gender == null ){
					item.setSexuality( (Integer)0 );
				}else if( gender instanceof Long ){
					item.setSexuality( ((Long)gender).intValue() );
				}else if(gender instanceof Integer ){
					item.setSexuality( (Integer)gender );
				}
				item.setFlag((Integer)r.get("flag"));
				item.setCv((Integer)r.get("cv"));
				item.setVid((String)r.get("vid"));
				item.setOwner((Integer)r.get("owner"));
				list.add( item );
			}
			return list;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			if( session != null )
				session.close();
		}
	}

	public List<ContactItem> getRunGroup(Integer userid, Integer owner, Integer from, Integer limit)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			List<Map<String,?>> result = mapper.selectRunGroup(userid, owner, from, limit);
			List<ContactItem> list = new ArrayList<ContactItem>();
			for( Map<String,?> r : result ){
				ContactItem item = new ContactItem();
				item.setId( (Integer)r.get("id") );
				String name = (String)r.get("name");
				item.setName( StringUtils.isBlank(name)?(String)r.get("account"):name );
				String avatar = (String)r.get("avatarImg");
				item.setAvatar( avatar==null?"":avatar );
				String thumb = (String)r.get("thumbImg");
				item.setAvatarThumb( thumb==null?"":thumb );
				item.setType( (Integer)r.get("type") );
				item.setAccount( (String)r.get("account") );
				item.setLocationid( r.get("locationid") == null?0:(Integer)r.get("locationid"));
				Object gender = r.get("sexuality");
				if( gender == null ){
					item.setSexuality( (Integer)0 );
				}else if( gender instanceof Long ){
					item.setSexuality( ((Long)gender).intValue() );
				}else if(gender instanceof Integer ){
					item.setSexuality( (Integer)gender );
				}
				item.setFlag((Integer)r.get("flag"));
				item.setCv((Integer)r.get("cv"));
				item.setVid((String)r.get("vid"));
				item.setOwner((Integer)r.get("owner"));
				String configure = (String)r.get("configure");
				JSONObject cfg = JSONObject.parseObject(configure);
				item.setLable(cfg.getString("desc"));

				list.add( item );
			}
			return list;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			if( session != null )
				session.close();
		}
	}

	public int getContactCount(Integer id,Integer type)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Integer> params = new HashMap<String,Integer>();
			params.put("id", id);
			params.put("type", type);
			int result = mapper.contactCount(params);
			return result;
		}catch(Exception e){
			e.printStackTrace();
			return -1;
		}finally{
			if( session != null )
				session.close();
		}
	}

	public int syncContactCount(Integer id,Integer type, Integer cv)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Integer> params = new HashMap<String,Integer>();
			params.put("id", id);
			params.put("type", type);
			params.put("cv", cv);
			int result = mapper.syncContactCount(params);
			return result;
		}catch(Exception e){
			e.printStackTrace();
			return -1;
		}finally{
			if( session != null )
				session.close();
		}
	}

	public int getRunGroupCount(Integer userid, Integer owner)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			int result = mapper.runGroupCount(userid, owner);
			return result;
		}catch(Exception e){
			e.printStackTrace();
			return -1;
		}finally{
			if( session != null )
				session.close();
		}
	}

	public String getUserAccountName(Integer id){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession(false);
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			return mapper.getUserAccount(id);
		}catch(Exception e){
			e.printStackTrace();
			session.rollback();
			return null;
		}finally{
			if( session != null )
				session.close();
		}
	}

	public RetCode addContact(Integer id, String userAccount, Integer contactID, Integer contactType, String message){
		if( id == contactID ){
			// 不能添加自己
			return RetCode.CONTACT_CANNOTADDSELF;
		}
		SqlSession session = null;
		try{
			if( contactType > 0 ){
				// 添加群组
				return joinGroup(id, userAccount, contactID, message);
			}

			session = DBUtils.getSqlSession(false);
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );

			//检查该联系人是否已经添加过
			int ret = mapper.containsContact(0, id, contactType, contactID, 0);
			if( ret > 0 ){
				return RetCode.CONTACT_EXIST;
			}

			//获取待添联系人的设置
			String settings = mapper.getUserSettingFlag(contactType, contactID);
			JSONObject userSettings = JSONObject.parseObject(settings);

			// 从settingFlag中判断待添加的联系人是否要求验证后再添加
			// 无需验证直接添加,1需要用户验证,2不允许添加
			int tp = userSettings.getIntValue("needAuth");
			if( tp == 0 ){
				RetCode retCode = addContactImpl(mapper, 
						0, id, userAccount,
						contactType,contactID, mapper.getUserAccount(contactID));

				if(retCode != RetCode.CONTACT_ADDOK) {
					session.rollback();
					return retCode;
				}

				NoticeUtils.makeNewFriendNoticeOfUser(id, contactID, message);
				return RetCode.CONTACT_ADDOK;
			}else if( tp == 1 ){
				// 生成添加好友的申请信息,等待用户验证通过后添加
				Map<String,Object> applyParams = new HashMap<String,Object>();
				// 验证人id
				applyParams.put("userid", contactID);
				// 申请人id
				applyParams.put("appuserid", id);
				// 该接口这个类型恒为0,标识申请人是普通人，且目标也是普通人
				applyParams.put("apptype", 0 );
				applyParams.put("targetid", id);
				applyParams.put("message", message);
				mapper.apply(applyParams);
				NoticeUtils.makeApplyNoticeOfUser(id, contactID, message);
				return RetCode.CONTACT_WAITFORAUTH;
			}else{
				return RetCode.CONTACT_ADD_REJECT;
			}
		}catch(Exception e){
			e.printStackTrace();
			session.rollback();
			return RetCode.SQL_ERROR;
		}finally{
			if( session != null )
				session.close();
		}
	}


	public RetCode delContact(Integer id,String account,Integer contactID,Integer contactType){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession(false);
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );

			int ret = mapper.containsContact(0, id, contactType, contactID, 0);
			if( ret == 0 ){
				return RetCode.CONTACT_NOT_EXIST;
			}

			String contactAccount = mapper.getUserAccount( contactID );
			// 从IM中删除
			IMService.getInstance().delFriend(account, contactAccount);

			Map<String,Integer> params = new HashMap<String,Integer>();

			// 从自己的联系人中删除
			params.put("usertype", 0 );
			params.put("userid", id); //for delFriend
			params.put("contacttype", contactType);
			params.put("contactid", contactID);
			mapper.delContact(params);

			// 从对方的联系人中把自己删除
			params.put("usertype", contactType);
			params.put("userid", contactID); //for delFriend
			params.put("contacttype", 0);
			params.put("contactid", id);
			mapper.delContact(params);

			session.commit();
			return RetCode.OK;
		}catch(Exception e){
			e.printStackTrace();
			session.rollback();
			return RetCode.SQL_ERROR;
		}finally{
			if( session != null )
				session.close();
		}
	}

	public List<ContactItem> searchUser(String term,Integer selfID){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> params = new HashMap<String,Object>();
			params.put("id", selfID);
			params.put("term",term);
			List<Map<String,?>> result = mapper.searchUser( params );
			List<ContactItem> list = new ArrayList<ContactItem>();
			for( Map<String,?> r : result ){
				ContactItem item = new ContactItem();
				item.setId( (Integer)r.get("id") );
				String name = (String)r.get("name");
				if( StringUtils.isEmpty(name) ){
					name = (String)r.get("account");
				}
				item.setName( name );
				String avatar = (String)r.get("avatarImg");
				item.setAvatar( avatar==null?"":avatar );
				String thumb = (String)r.get("thumbImg");
				item.setAvatarThumb( thumb==null?"":thumb );
				item.setType( 0 );
				item.setLocationid( r.get("locationid") == null ? 0: (Integer)r.get("locationid"));
				item.setAccount((String)r.get("account"));
				list.add( item );
			}
			return list;
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}finally{
			if( session != null )
				session.close();
		}	
	}

	public List<ApplicationInfo> getApplications(Integer id,String appTime){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession(true);
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> params = new HashMap<String,Object>();
			params.put("id", id);
			params.put("appTime",appTime);
			List<Map<String,?>> result = mapper.getApplications( params );
			List<ApplicationInfo> reList =new ArrayList<ApplicationInfo>();
			for( Map<String,?> row : result ){
				ApplicationInfo item = new ApplicationInfo();
				item.setAppId( ((Long)row.get("appid")).intValue() );
				item.setId( (Integer)row.get("id") );
				String name = (String)row.get("name");
				item.setName( StringUtils.isBlank(name)?(String)row.get("account"):name );
				item.setTargetid( (Integer)row.get("targetid") );
				String avatar = (String)row.get("avatarImg");
				item.setAvatar( avatar==null?"":avatar );
				String thumb = (String)row.get("thumbImg");
				item.setAvatarThumb( thumb==null?"":thumb );
				Object type = row.get("type") ;
				if( type instanceof Integer )
					item.setType( (Integer)type );
				else if( type instanceof Long )
					item.setType( ((Long)type).intValue() );
				Object at = row.get("apptime");
				item.setApplyTime( at != null ? at.toString(): null );
				item.setApplyMsg( StringUtils.isBlank( (String)row.get("msg"))?"":(String)row.get("msg") );
				Object gender = row.get("sexuality");
				if( gender instanceof Integer )
					item.setSexuality( (Integer)gender );
				else if( gender instanceof Long )
					item.setSexuality( ((Long)gender).intValue() );
				Object appType = row.get("applyType");
				if( appType instanceof Integer )
					item.setApplyType( (Integer)appType );
				else if( appType instanceof Long )
					item.setApplyType( ((Long)appType).intValue() );
				reList.add( item );
			}
			return reList;
		}catch(Exception e){
			e.printStackTrace();
			session.rollback();
		}finally{
			if( session != null )
				session.close();
		}
		return Collections.emptyList();
	}

	public boolean processApplication(Integer userID,String accountName,
			Integer contactID,Integer appid,Integer apptype,String result){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession(false);
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );

			if( result.compareToIgnoreCase("accept") == 0 ){
				if(apptype == 0){
					String contactName = mapper.getUserAccount(contactID);

					RetCode retCode = addContactImpl(mapper, 
							0, userID, accountName, 
							apptype, contactID, contactName);

					if(retCode != RetCode.CONTACT_ADDOK) {
						session.rollback();
						System.out.println("add friend["+contactName+"] faild:"+accountName);
						return false;
					}

					NoticeUtils.makeNewFriendNoticeOfUser(userID, contactID, "同意了你加为好友的申请");
				}else{
					// 处理邀请加群的请求
					Group g = mapper.getGroupInfo(contactID);

					RetCode retCode = addContactImpl(mapper, 
							0, userID, accountName, 
							apptype, contactID, g.getVid());

					if(retCode != RetCode.CONTACT_ADDOK) {
						session.rollback();
						System.out.println("join group["+g.getVid()+"] faild:"+accountName);
						return false;
					}
				}

				mapper.processApplication(appid, 1);
			}else{
				mapper.processApplication(appid, 2);
			}

			session.commit();
			return true;
		}catch(Exception e){
			e.printStackTrace();
			session.rollback();
		}finally{
			if( session != null )
				session.close();
		}
		return false;
	}

	public Integer createGroup(Integer ownerID,String ownerAccount,String groupName,String desc,
			boolean isPublic,int maxUsers,boolean approval,int groupType,List<Member> members,String address,
			String coord, String avatarImg,String coverImgs){
		String groupID = IMService.getInstance().createChatGroup(groupName, desc, isPublic, maxUsers, 
				approval, ownerAccount, members);
		if( groupID == null ){
			return null;
		}
		// 将分组设置保存起来
		JSONObject config = new JSONObject();
		config.put("maxUsers", maxUsers);
		config.put("users",(members!=null)?members.size()+1:1);
		config.put("desc", desc);
		config.put("coord", coord);
		config.put("coordname", address);
		if( coverImgs != null ){
			config.put("coverImg",coverImgs);
		}

		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession(false);
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			List<Integer> contactList = new ArrayList<Integer>();
			Map<String,Object> params = new HashMap<String,Object>();
			params.put("vid", groupID );
			params.put("owner", ownerID);
			params.put("name", groupName);

			params.put("type", groupType );
			contactList.add( ownerID );
			JSONObject settings = new JSONObject();
			if( approval && groupType != 1){
				settings.put("needAuth", 1);
			}else{
				settings.put("needAuth", 0);
			}
			if( isPublic ){
				settings.put("public", true);
			}else{
				settings.put("public", false);
			}
			if( coverImgs != null ){
				settings.put("coverImg",coverImgs);
			}
			params.put("flag", settings.toJSONString() );
			params.put("configure", config.toJSONString());
			params.put("address", address);
			params.put("avatarImg", avatarImg);
			// 创建虚拟分组用户
			int ret = mapper.createGroup(params);
			int vUserID = 0;
			if( ret == 1 ){
				vUserID = (Integer)params.get("id");
				String[] args = coord.split(",");
				Integer locid = CloudMapService.getInstance().createUserLocData(groupName, args[0], args[1], 1, vUserID );
				if( locid > 0 ){
					mapper.updateGroup(locid, vUserID);
				}
			}else{
				session.rollback();
				return null;
			}
			// 将虚拟分组用户加为自己的联系人
			Map<String,Integer> ps = new HashMap<String,Integer>();
			ps.put("userid", ownerID);
			ps.put("contactid",vUserID);
			ps.put("usertype", 0);
			ps.put("contacttype",groupType);
			mapper.addContact(ps);
			// 如果存在成员列表则将新创建的组添加到成员的联系人列表中
			if(members != null) {
				for( Member member:members ){
					ps.put("userid", member.getId());
					mapper.addContact(ps);
					contactList.add( member.getId() );
				}
			}
			// 将成员和拥有者作为联系人加入到虚拟分组的联系人列表中作为成员
			ps.put("userid", vUserID );
			ps.put("contacttype",0);
			ps.put("usertype", groupType);
			for(Integer id:contactList ){
				ps.put("contactid", id);
				mapper.addContact(ps);
			}
			session.commit();
			return vUserID;
		}catch(Exception e){
			e.printStackTrace();
			session.rollback();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}


	public RetCode deleteGroup(Integer userid,Integer groupID)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			// 获取群组基本信息
			Group g = mapper.getGroupInfo(groupID);
			if( g == null ){
				return RetCode.TARGET_NOT_EXIST;
			}
			if( Integer.parseInt(g.getOwner()) != userid ){
				return RetCode.NOT_OWNER;
			}else{
				boolean ret = IMService.getInstance().deleteChatGroup(g.getVid());
				if( ret ){
					Map<String,Integer> ps = new HashMap<String,Integer>();
					ps.put("groupid", groupID);
					ps.put("type", g.getType());
					mapper.deleteGroup(ps);
					return RetCode.OK;
				}else{
					return RetCode.IM_DELETEGROUPFAILD;
				}
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public RetCode getGroupMembers(Integer userid,Integer groupid,Map<String,Object> members,Integer from,Integer limit){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );

			// 检查属性是否为公开
			String settingFlag = mapper.getUserSettingFlag(1, groupid);
			Map<String,Integer> params = new HashMap<String,Integer>();
			params.put("type", 1 );
			params.put("id", groupid);
			List<Map<String,?>> result = mapper.selectAllContact(params);
			JSONObject settings = JSONObject.parseObject(settingFlag);
			if( settings.containsKey("public") && !settings.getBooleanValue("public") ){
				// 非公开的需要验证该用户是否是分组成员，非成员则不能查看成员列表
				boolean isMember = false;
				for(Map<String,?> row:result){
					int id = (Integer)row.get("id");
					if( id == userid ){
						isMember = true;
						break;
					}
					continue;
				}
				if( !isMember ){
					return RetCode.CONTACT_NOT_MEMBER;
				}
			}
			members.put("total", result.size() );
			int n=0,count=0;
			List<ContactItem> list = new ArrayList<ContactItem>();
			for(Map<String,?> r:result){
				if( from!=null && n<from ){
					n++;
					continue;
				}
				ContactItem item = new ContactItem();
				item.setId( (Integer)r.get("id") );
				item.setName( (String)r.get("name") );
				String avatar = (String)r.get("avatarImg");
				item.setAvatar( avatar==null?"":avatar );
				String thumb = (String)r.get("thumbImg");
				item.setAvatarThumb( thumb==null?"":thumb );
				item.setType( (Integer)r.get("type") );
				item.setAccount( (String)r.get("account") );
				item.setLocationid( r.get("locationid") == null?0:(Integer)r.get("locationid"));
				list.add( item );
				if(limit!=null ){
					count++;
					if( count>=limit )
						break;
				}
			}
			members.put("data", list );
			return RetCode.OK;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public RetCode invite(Integer userid,Integer targetid,Integer groupID){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );

			// 获取群组基本信息
			Group g = mapper.getGroupInfo(groupID);
			if( g == null ){
				return RetCode.TARGET_NOT_EXIST;
			}
			// 从群组中获取群组设置,验证是否达到最大限制
			JSONObject config = JSONObject.parseObject(g.getConfigure());
			int maxUsers = config.getInteger("maxUsers");
			if( maxUsers <= g.getUerCount() ){
				return RetCode.MAX_LIMITED;
			}

			JSONObject settings = JSONObject.parseObject(g.getSettingFlag());
			// 检查群是否允许自行添加新用户
			int approval = settings.getIntValue("needAuth");
			if( approval == 2 ){
				return RetCode.CONTACT_ADD_REJECT;
			}

			//获取待添联系人的设置
			String userSettingsflag = mapper.getUserSettingFlag(0, targetid);

			//判断新增的目标用户是否允许被邀请
			JSONObject userSettings = JSONObject.parseObject(userSettingsflag);
			int needAuth = userSettings.getInteger("needAuth");
			if( needAuth == 2 )
			{
				return RetCode.CONTACT_ADD_REJECT;
			}

			//检查该联系人是否已经添加过
			int ret = mapper.containsContact(0, targetid, g.getType(), groupID, 0);
			if( ret > 0 ){
				return RetCode.CONTACT_EXIST;
			}
			if( needAuth == 0 ){
				RetCode retCode = addContactImpl(mapper, 
						0, targetid, mapper.getUserAccount(targetid), 
						g.getType(), groupID, g.getVid());

				if(retCode != RetCode.CONTACT_ADDOK) {
					session.rollback();
					return retCode;
				}

				NoticeUtils.makeNewFriendNoticeOfUser(groupID, targetid, "被邀请加入了["+g.getName()+"]");
				return RetCode.CONTACT_ADDOK;
			}else{
				// 申请被对方批准后才能添加
				Map<String,Object> applyParams = new HashMap<String,Object>();
				applyParams.put("userid", targetid);
				applyParams.put("appuserid", userid);
				applyParams.put("apptype", g.getType() );
				applyParams.put("targetid", groupID);
				applyParams.put("message", "");
				mapper.apply(applyParams);
				NoticeUtils.makeApplyNoticeOfUser(groupID, targetid, "邀请你加入["+g.getName()+"]");
				return RetCode.OK;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public RetCode joinGroup(Integer userid, String account, Integer groupID, String message){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );

			// 获取群组基本信息
			Group g = mapper.getGroupInfo(groupID);
			if( g == null ){
				return RetCode.TARGET_NOT_EXIST;
			}

			// 从群组中获取群组设置,验证是否达到最大限制
			JSONObject config = JSONObject.parseObject(g.getConfigure());
			int maxUsers = config.getInteger("maxUsers");
			if( maxUsers <= g.getUerCount() ){
				return RetCode.MAX_LIMITED;
			}

			JSONObject settings = JSONObject.parseObject(g.getSettingFlag());
			// 检查群是否允许自行添加新用户
			int approval = settings.getIntValue("needAuth");
			if( approval==2 ){
				return RetCode.CONTACT_ADD_REJECT;
			}

			//检查该联系人是否已经添加过该群组
			int ret = mapper.containsContact(0, userid, g.getType(), groupID, 0);
			if( ret > 0 ){
				return RetCode.CONTACT_EXIST;
			}

			if( approval == 0 ){
				RetCode retCode = addContactImpl(mapper, 
						0, userid, account,
						g.getType(), groupID, g.getVid());

				if(retCode != RetCode.CONTACT_ADDOK) {
					session.rollback();
					return retCode;
				}

				NoticeUtils.makeNewFriendNoticeOfUser(userid, groupID, message);
				return RetCode.CONTACT_ADDOK;
			}else{
				// 申请被群主管理员批准后才能添加
				Map<String,Object> applyParams = new HashMap<String,Object>();
				// 群主管理员
				applyParams.put("userid", Integer.valueOf(g.getOwner()));
				// 发起邀请/申请的人
				applyParams.put("appuserid", userid);
				// 发起申请的人类型  -1标识申请人申请自己加入目标群组联系人
				applyParams.put("apptype", -1 );
				// 添加目标的id
				applyParams.put("targetid", groupID);

				applyParams.put("message", message);

				mapper.apply(applyParams);

				NoticeUtils.makeApplyNoticeOfUser(userid, Integer.valueOf(g.getOwner()), "申请加入["+g.getName()+"]");

				return RetCode.CONTACT_WAITFORAUTH;
			}
		}catch(Exception e){
			e.printStackTrace();
			return RetCode.SQL_ERROR;
		}finally{
			if( session != null )
				session.close();
		}
	}


	public RetCode removeUserFromGroup(Integer userid,Integer targetid,Integer groupID){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession(false);
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );

			// 获取群组基本信息
			Group g = mapper.getGroupInfo(groupID);
			if( g == null ){
				return RetCode.TARGET_NOT_EXIST;
			}
			int owner = Integer.valueOf(g.getOwner());
			// 若移除的不是本人，则检测是否具有权限
			if( userid != targetid ){
				if( owner != userid ){
					return RetCode.NOT_OWNER;
				}
			}

			if( targetid == owner ){
				// 若拥有者要退出该群,则当删除群处理
				boolean ret = IMService.getInstance().deleteChatGroup(g.getVid());
				if( ret ){
					Map<String,Integer> ps = new HashMap<String,Integer>();
					ps.put("groupid", groupID);
					ps.put("type", g.getType());
					mapper.deleteGroup(ps);
					session.commit();
					return RetCode.OK;
				}else{
					return RetCode.IM_DELETEGROUPFAILD;
				}
			}

			int ret = mapper.containsContact(g.getType(), groupID, 0, targetid, 0);
			if( ret == 0 ){
				return RetCode.CONTACT_NOT_EXIST;
			}

			String contactAccount = mapper.getUserAccount( targetid );
			// 从IM中删除
			IMService.getInstance().remove(g.getVid(), contactAccount);

			Map<String,Integer> params = new HashMap<String,Integer>();

			// 从targetid的联系人中删除
			params.put("usertype", 0);
			params.put("userid", targetid);
			params.put("contactid", groupID);
			params.put("contacttype", g.getType() );
			mapper.delContact(params);

			// 从组联系人中把targetid删除
			params.put("userid", groupID); //for delFriend
			params.put("contactid", targetid);
			params.put("contacttype", 0);
			params.put("usertype",  g.getType() );
			mapper.delContact(params);

			session.commit();
			return RetCode.OK;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}


	/**
	 * 发布朋友圈信息
	 */
	public int publishTalk(Integer userid,String message,String attachment,int settingFlag,
			String accesslist,int accesslistType,String talkType,String location,String avatar)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession(false);
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("userid", userid);
			map.put("message", message);
			map.put("attachment", attachment);
			map.put("settingFlag",settingFlag);
			map.put("talkType", talkType);
			map.put("location", location);
			List<String> list = new ArrayList<String>();
			if( !isPublic(settingFlag) ){
				map.put("list",accesslist);
				map.put("type", accesslistType);
				mapper.createAccesslist( map );
				Integer accid = (Integer)map.get("id");
				map.put("accessid", accid);
				if( accesslistType == 0){
					String[] accessUsers = accesslist.split(",");
					list = Arrays.asList(accessUsers);
				}else{
					// 禁止列表
					Map<String,Integer> params = new HashMap<String,Integer>();
					params.put("id", userid);
					params.put("type", 0);
					List<Map<String,?>> result = mapper.selectAllContact( params );

					for(Map<String,?> row:result){
						String cid = String.valueOf(row.get("contactid"));
						if( accesslist.indexOf( cid ) == -1 ){
							list.add(cid);
						}
					}
				}
			}else{
				// 公开，只发好友通知
				Map<String,Integer> params = new HashMap<String,Integer>();
				params.put("id", userid);
				params.put("type", 0);
				List<Map<String,?>> result = mapper.selectAllContact( params );
				for(Map<String,?> row:result){
					String cid = String.valueOf(row.get("id"));
					Integer type = (Integer)row.get("type");
					if( type == 0)
						list.add(cid);
				}
			}
			int ret = mapper.talk(map);
			int talkID = (Integer)map.get("id");
			RetCode rc =  ret>0?RetCode.OK:RetCode.TALK_PUBLISH_FAILD;
			if( rc == RetCode.OK )
			{
				NoticeUtils.makeTalkNoticeOfUser(userid, list, avatar==null?"null":avatar+"#"+talkID+"#"+message);
				session.commit();
				return talkID;
			}else{
				session.rollback();
				return -1;
			}

		}catch(Exception e){
			e.printStackTrace();
			session.rollback();
		}finally{
			if( session != null )
				session.close();
		}
		return -1;
	}

	public RetCode updateImageOfTalk(Integer talkid,String imgToken,Integer index)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Talk talk = mapper.getTalk(talkid);
			if( "photo".compareTo(talk.getType()) != 0 ){
				return RetCode.TALK_TYPE_INVALID;
			}
			String attachment = talk.getAttachment();
			JSONObject object = (JSONObject)JSON.parse(attachment);
			int nImages = object.getInteger("count");
			if( index<0 || index >= nImages ){
				return RetCode.TALK_INDEX_OUTOFRANGE;
			}
			JSONArray photos = object.getJSONArray("photos");
			JSONObject photo = photos.getJSONObject(index);
			photo.put("token", imgToken);
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("talkid", talkid);
			map.put("attachment", object.toJSONString() );
			mapper.updateTalk(map);
			return RetCode.OK;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public Talk getTalkInfo(Integer talkid){
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			return mapper.getTalk(talkid);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}

	/**
	 * 评论发布的信息
	 */
	public int comment(Integer talkid,String comment,Integer userid,String userName,Integer commentType,Integer replyTo)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("userid", userid);
			map.put("talkid", talkid);
			map.put("comment", comment);
			map.put("commentType", commentType);
			map.put("userName", userName);
			if( replyTo != null )
				map.put("replyTo", replyTo);
			int ret = mapper.comment(map);
			if( ret > 0 ){
				// 获取talkid对应作者
				Talk talk = mapper.getTalk(talkid);
				NoticeUtils.makeCommentNoticeOfUser(userid,talk.getAuthorid(), talkid+"#"+map.get("id"));
				return (Integer)map.get("id");
			}
			return 0;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return 0;
	}

	public RetCode deleteTalk(Integer talkid,Integer userid)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("userid", userid);
			map.put("id", talkid);
			mapper.delTalk(map);
			return RetCode.OK;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public RetCode deleteComment(Integer commentid,Integer talkid,Integer userid)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("userid", userid);
			map.put("talkid", talkid);
			map.put("commentid", commentid);
			int ret = mapper.delTalkComment(map);
			return ret>0?RetCode.OK:RetCode.TALK_DELETE_FAILD;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}


	public List<Talk> getUserTalks(Integer userid,Integer querierID,Integer from)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("userid", userid);
			map.put("querier", querierID);
			map.put("from", from);
			List<Talk> result =  mapper.getUserTalks(map);
			if( result == null || result.size() == 0)
				return Collections.emptyList();
			List<Integer> talkIDS = new ArrayList<Integer>();
			for(Talk m:result)
			{
				talkIDS.add( m.getId() );
			}
			//获取各个talk的评论信息
			map.clear();
			map.put("list", talkIDS);
			List<Comment> comments = mapper.getTalkCommentList(map);
			for( Talk m:result)
			{
				for(Comment c:comments){
					if( c.getTalkid() == m.getId() ){
						m.getComments().add(c);
					}
				}
			}

			return result;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}


	public List<Talk> syncFirendsTalks(Integer userid,String cv,Integer direction)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("userid", userid);
			map.put("cv", cv);
			map.put("direction", direction);
			List<Talk> result =  mapper.syncFriendsTalks(map);
			if( result == null )
				return null;
			if( result.isEmpty() ){
				return result;
			}
			List<Integer> talkIDS = new ArrayList<Integer>();
			for(Talk m:result)
			{
				talkIDS.add( m.getId() );
			}
			//获取各个talk的评论信息
			map.clear();
			map.put("list", talkIDS);
			List<Comment> comments = mapper.getTalkCommentList(map);
			for( Talk m:result)
			{
				for(Comment c:comments){
					if( c.getTalkid() == m.getId() ){
						m.getComments().add(c);
					}
				}
			}
			return result;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}



	public List<Comment> getTalkComments(List<Integer> talks)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("list", talks);
			List<Comment> result =  mapper.getTalkCommentList(map);
			if( result == null )
				return Collections.emptyList();
			return result;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}

	public List<Comment> getTalkDetail(int talkid)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			List<Comment> result =  mapper.getTalkComments(talkid);
			if( result == null )
				return Collections.emptyList();
			return result;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}

	public List<Talk> getTalks(Integer userid,Integer from,Integer limit)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("userid", userid);
			map.put("from", from);
			map.put("limit", limit);
			List<Talk> result =  mapper.getFriendsTalks(map);
			if( result == null )
				return null;
			if( result.isEmpty() ){
				return result;
			}
			List<Integer> talkIDS = new ArrayList<Integer>();
			for(Talk m:result)
			{
				talkIDS.add( m.getId() );
			}
			//获取各个talk的评论信息
			map.clear();
			map.put("list", talkIDS);
			List<Comment> comments = mapper.getTalkCommentList(map);
			for( Talk m:result)
			{
				for(Comment c:comments){
					if( c.getTalkid() == m.getId() ){
						m.getComments().add(c);
					}
				}
			}
			return result;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}

	public JSONArray get3Photos(int userid)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("userid", userid);
			List<Map<String,?>> res = mapper.get3PhotoInAlbum(map);
			JSONArray result = new JSONArray();
			for( Map<String,?> r : res ){
				String attachment = (String)r.get("attachment");
				JSONObject info = JSONObject.parseObject(attachment);
				JSONArray photos = info.getJSONArray("photos");
				for( int i=0;i<photos.size();++i){
					result.add(photos.get(i));
					if( result.size() == 3 ){
						return result;
					}
				}
			}
			return result;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}

	public JSONArray getUserContactsFriends(int userid)
	{
		SqlSession session = null;
		try{
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			List<Map<String,?>> res = mapper.getContactsFriends(userid);
			JSONArray result = new JSONArray();
			for( Map<String,?> r : res ){
				String cid = (String)r.get("cid");
				String phone = (String)r.get("phone");
				Integer accountid = (Integer)r.get("account_id");
				String account = (String)r.get("account");
				Integer sex = (Integer) r.get("sexuality");
				String avatarImg = (String)r.get("avatarImg");
				String name = (String)r.get("name");
				if(StringUtils.isBlank(name))
					name = account;
				JSONObject info = new JSONObject();
				info.put("cid", cid);
				info.put("phone", phone);
				info.put("userid", accountid);
				info.put("account", account);
				info.put("sex", sex);
				info.put("avatar", avatarImg);
				info.put("name", name);
				result.add( info );
			}
			return result;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}

	public RetCode addUserContacts(int userid,JSONArray data)
	{

		SqlSession session = null;
		try{
			Map<String,Object> map = new HashMap<String,Object>();
			List<Map<String,Object>> ps = new ArrayList<Map<String,Object>>();
			int nContacts = data.size();
			if( nContacts == 0 ){
				return RetCode.OK;
			}
			for(int i=0;i<nContacts;++i)
			{
				JSONObject obj = (JSONObject)data.get(i);
				Map<String,Object> mp = new HashMap<String,Object>();
				mp.put("cid",obj.get("cid"));
				mp.put("userid", userid);
				mp.put("phone",obj.get("phone"));
				ps.add( mp );
			}
			map.put("list", ps);
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			mapper.addContacts(map);
			return RetCode.OK;
		}catch(Exception e){
			if( e instanceof MySQLIntegrityConstraintViolationException){
				return RetCode.OK;
			}
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public RetCode deleteUserContacts(int userid,JSONArray data)
	{

		SqlSession session = null;
		try{
			Map<String,Object> map = new HashMap<String,Object>();
			List<Map<String,Object>> ps = new ArrayList<Map<String,Object>>();
			int nContacts = data.size();
			if( nContacts == 0 ){
				return RetCode.OK;
			}
			for(int i=0;i<nContacts;++i)
			{
				JSONObject obj = (JSONObject)data.get(i);
				Map<String,Object> mp = new HashMap<String,Object>();
				mp.put("cid",obj.get("cid"));
				mp.put("userid", userid);
				ps.add( mp );
			}
			map.put("list", ps);
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			mapper.deleteContacts(map);
			return RetCode.OK;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return RetCode.SQL_ERROR;
	}

	public JSONArray getLocalUsers(int userid,String city,int type)
	{
		Map<Integer,String> res = CloudMapService.getInstance().getLocalUsers(city, type);
		if( res==null ||res.size() == 0){
			return new JSONArray();
		}
		SqlSession session = null;
		try{
			Map<String,Object> map = new HashMap<String,Object>();
			List<Integer> ids = new ArrayList<Integer>();
			ids.addAll( res.keySet() );			
			map.put("list", ids);
			map.put("type", type);
			session = DBUtils.getSqlSession();
			BasicSqlMapper mapper = session.getMapper( BasicSqlMapper.class );
			List<Map<String,?>> result = mapper.getLocalUsers(map);
			JSONArray retVal = new JSONArray();
			for(Map<String,?> m : result ){
				JSONObject item = new JSONObject();
				if( type == 0 ){
					Integer uid = (Integer)m.get("userid");
					String name = (String)m.get("name");
					String avatar = (String)m.get("avatarImg");
					String account = (String)m.get("account");
					Integer gender = (Integer)m.get("sexuality");
					String label = (String)m.get("label");
					String coord = res.get(uid);
					item.put("userid", uid);
					item.put("name", StringUtils.isBlank(name)?account:name);
					item.put("avatar", avatar);
					item.put("account",account);
					item.put("gender", gender);
					item.put("location", coord);
					item.put("label", label);
				}else{
					Integer uid = (Integer)m.get("userid");
					String name = (String)m.get("name");
					String avatar = (String)m.get("avatarImg");
					String vid = (String)m.get("vid");
					String configure = (String)m.get("configure");
					String coord = res.get(uid);
					String address = (String)m.get("location");
					Integer members = (Integer)m.get("members");
					item.put("userid", uid);
					item.put("name", name);
					item.put("avatar", avatar);
					item.put("vid",vid);
					item.put("configure", configure);
					item.put("location", coord);
					item.put("address", address);
					item.put("memberCount", members);
				}
				retVal.add(item);
			}
			return retVal;
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if( session != null )
				session.close();
		}
		return null;
	}

	private boolean isPublic(int flag){
		int ret = (flag>>2)&1;
		if( ret > 0 )
			return true;
		return false;
	}

	private RetCode addContactImpl(BasicSqlMapper mapper, 
			Integer userType,
			Integer userId,
			String userAccount,
			Integer contactType, 
			Integer contactId,
			String contactAccount) {
		//检查该联系人是否删除过
		int ret = mapper.containsContact(userType, userId, contactType, contactId, 1);

		Map<String,Integer> params = new HashMap<String,Integer>();
		if(ret > 0) {
			// 更新status为0，重新加为好友
			params.put("userid", userId);
			params.put("usertype", userType);
			params.put("contactid", contactId);
			params.put("contacttype",contactType);
			mapper.addContactUpdateFlag(params);

			params.put("userid", contactId);
			params.put("usertype", contactType);
			params.put("contactid", userId);
			params.put("contacttype",userType);
			mapper.addContactUpdateFlag(params);
		} else {
			// 互相加为好友
			params.put("userid", userId);
			params.put("usertype", userType);
			params.put("contactid", contactId);
			params.put("contacttype",contactType);
			mapper.addContact(params);

			params.put("userid", contactId);
			params.put("usertype", contactType);
			params.put("contactid", userId);
			params.put("contacttype",userType);
			mapper.addContact(params);
		}

		// 在IM系统中同时添加为好友
		boolean stat = false;

		if(contactType == 0) {
			stat = IMService.getInstance().addFriend(userAccount, contactAccount);
		} else {
			stat = IMService.getInstance().joinGroup(contactAccount, userAccount);
		}

		if(!stat) {
			return RetCode.IM_ADDFRIENDERROR;
		}

		return RetCode.CONTACT_ADDOK;
	}
}
